package yatan.crawler.single;

import java.io.FileInputStream;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class ConfigUtility {
    private ConfigUtility() {
    }

    public static Properties loadConfigFile(String configFile) {
	// load configuration file
	Properties properties = new Properties();
	InputStream is = ConfigUtility.class.getClassLoader().getResourceAsStream(configFile);
	try {
	    // if the file cannot be found in class path, try it from file
	    // system
	    if (is == null) {
		is = new FileInputStream(configFile);
	    }

	    properties.load(is);
	} catch (FileNotFoundException e) {
	    throw new CrawlerConfigurationException("Cannot find configuration file: " + configFile, e);
	} catch (IOException e) {
	    throw new CrawlerConfigurationException("Cannot read configuration file: " + configFile + ". IO error: "
		    + e.getMessage());
	}

	return properties;
    }

    public static String readStringProperty(Properties properties, String key, boolean required, String defaultValue) {
	try {
	    String value = (String) properties.get(key);
	    if (value == null || value.trim().length() == 0) {
		if (required) {
		    throw new CrawlerConfigurationException("Required property " + key
			    + " does not exist of is empty in configuration.");
		}

		return defaultValue;
	    }

	    return value;
	} catch (ClassCastException e) {
	    throw new CrawlerConfigurationException("The property " + key + " must be a string.");
	}
    }

    public static int readIntProperty(Properties properties, String key, boolean required, int defaultValue) {
	try {
	    return Integer.parseInt(readStringProperty(properties, key, required, Integer.toString(defaultValue)));
	} catch (NumberFormatException e) {
	    throw new CrawlerConfigurationException("The property " + key + " must be an integer.");
	}
    }

    public static <T> T createObject(Properties properties, String key, Class<T> expectedType) {
	String className = readStringProperty(properties, key, true, null);
	try {
	    return expectedType.cast(Class.forName(className).newInstance());
	} catch (InstantiationException e) {
	    throw new CrawlerConfigurationException("Cannot create object with the key " + key
		    + ". Instantiation error: " + e.getMessage(), e);
	} catch (IllegalAccessException e) {
	    throw new CrawlerConfigurationException("Cannot create object with the key " + key + ". Illegal access: "
		    + e.getMessage(), e);
	} catch (ClassNotFoundException e) {
	    throw new CrawlerConfigurationException("Cannot create object with the key " + key + ". The class "
		    + className + " can not be found.", e);
	} catch (ClassCastException e) {
	    throw new CrawlerConfigurationException("Cannot create object with the key " + key
		    + ". The object of type " + className + " is not an instance of " + expectedType, e);
	}
    }
}
